/**
 * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd
 * author: Benjo Lei <benjo.lei@rock-chips.com>
 *
 * This software is licensed under the terms of the GNU General Public
 * License version 2, as published by the Free Software Foundation, and
 * may be copied, distributed, and modified under those terms.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include "wifi_management.h"

#include <dirent.h>
#include <net/if.h>
#include <stdio.h>
#include <string.h>
#include <time.h>

#include <unistd.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/vfs.h>

#include "common.h"
#include "parameter.h"
#include "menu_commond.h"
#include "wifi_ota_interface.h"
#include "wlan_service_client.h"
#include "wifi_setting_interface.h"
#include "wifi_debug_interface.h"
#include "fs_manage/fs_storage.h"
#include "fs_manage/fs_sdcard.h"
#include "ueventmonitor/usb_sd_ctrl.h"
#include "fly_server.h"

#define RTP_TS_TRANS_ENABLE
#define MAX_CLIENT_LIMIT_NUM   15

#define UDPPORT 18889
#define TCPPORT 8888

static int broadcast_fd = -1;
static int tcp_server_fd = -1;
static int tcp_server_tab[MAX_CLIENT_LIMIT_NUM];

static pthread_t broadcast_tid;
static pthread_t tcp_server_tid;
static int g_wifi_is_running;
static int live_client_num;
static int link_client_num = 0;
char SSID[33];
char PASSWD[65];

#define STR_DEBUG_ARGSETTING    "CMD_DEBUG_ARGSETTING"

static int cmd_resolve(int fd, char *cmdstr);

int runapp(char *cmd)
{
	char buffer[BUFSIZ] = {0};
	FILE *read_fp;
	int chars_read;
	int ret;

	read_fp = popen(cmd, "r");
	if (read_fp != NULL) {
		chars_read = fread(buffer, sizeof(char), BUFSIZ - 1, read_fp);
		if (chars_read > 0)
			ret = 1;
		else
			ret = -1;
		pclose(read_fp);
	} else {
		ret = -1;
	}
}

int linux_get_mac(char *mac)
{
	int sockfd;
	struct ifreq tmp;
	char mac_addr[30] = {0};

	sockfd = socket(AF_INET, SOCK_STREAM, 0);
	if (sockfd < 0) {
		perror("create socket fail\n");
		return -1;
	}

	memset(&tmp, 0, sizeof(struct ifreq));
	strncpy(tmp.ifr_name, "wlan0", sizeof(tmp.ifr_name) - 1);
	if ((ioctl(sockfd, SIOCGIFHWADDR, &tmp)) < 0) {
		printf("mac ioctl error\n");
		return -1;
	}

	sprintf(mac_addr, "%02x%02x%02x%02x%02x%02x",
		(unsigned char)tmp.ifr_hwaddr.sa_data[0],
		(unsigned char)tmp.ifr_hwaddr.sa_data[1],
		(unsigned char)tmp.ifr_hwaddr.sa_data[2],
		(unsigned char)tmp.ifr_hwaddr.sa_data[3],
		(unsigned char)tmp.ifr_hwaddr.sa_data[4],
		(unsigned char)tmp.ifr_hwaddr.sa_data[5]
	       );
	close(sockfd);
	memcpy(mac, mac_addr, strlen(mac_addr));

	return 0;
}

extern void (*sdcard_event_call)(int cmd, void *msg0, void *msg1);
int sdcard_is_full()
{
	long long total_size;
	long long free_size;
	fs_sdcard_check_capacity(&free_size,&total_size,NULL);
	if (free_size < SD_FREE_CAPATITY(total_size)) {
		if (sdcard_event_call)
			(*sdcard_event_call)(SD_FULL, 0, (void *)(getSD_full_strategy()));
		return 1;
	}else{
		return 0;
	}
}

int get_g_wifi_is_running(void)
{
	return g_wifi_is_running;
}

static int tcp_func_delete_file(int nfp, char *buffer)
{
	const char *fault = "CMD_DELFAULT";
	const char *success = "CMD_DELSUCCESS";
	char name[128] = {0}, type[64] = {0};
	int len;
	int form;
	int type_num, *camera_type;
	char path[512] = {0};
	char *ptr;

	printf("delete file cmd : %s\n", buffer);

	ptr = strstr(buffer, "FORM:");
	if (ptr == NULL) {
		printf("strstr FORM fault\n");
		return -1;
	}
	ptr[0] = 0;
	ptr = &ptr[5];
	form = atoi(ptr);

	ptr = strstr(buffer, "TYPE:");
	if (ptr == NULL) {
		printf("strstr TYPE fault\n");
		return -1;
	}
	ptr[0] = 0;
	ptr = &ptr[5];
	strcpy(type, ptr);

	ptr = strstr(buffer, "NAME:");
	if (ptr == NULL) {
		printf("strstr NAME fault\n");
		return -1;
	}
	ptr[0] = 0;
	ptr = &ptr[5];
	strcpy(name, ptr);

	printf("Name = %s , TYPE = %s , FORM = %d\n", name, type, form);

	type_num = fs_storage_filetypenum_get();
	camera_type = fs_storage_filetypetbl_get();

	strcat(path, fs_storage_folder_get_bytype(*(camera_type + form),
			THUMBFILE_TYPE));
	strcat(path, "/");
	strcat(path, name);
	len = strlen(path);
	path[len - 1] = 'g';
	path[len - 2] = 'p';
	path[len - 3] = 'j';
	printf("delete preview:%s\n", path);
	if (fs_storage_remove(path, 1) < 0) {
		perror("remove\n");
	} else {
		printf("delete %s success\n", path);
	}
	memset(path, 0, sizeof(path));

	if (strcmp(type, "normal") == 0)
		strcat(path, fs_storage_folder_get_bytype(*(camera_type + form),
				VIDEOFILE_TYPE));
	else if (strcmp(type, "lock") == 0)
		strcat(path, fs_storage_folder_get_bytype(*(camera_type + form),
				LOCKFILE_TYPE));
	else if (strcmp(type, "picture") == 0)
		strcat(path, fs_storage_folder_get_bytype(*(camera_type + form), PICFILE_TYPE));

	strcat(path, "/");
	strcat(path, name);
	printf("path:%s\n", path);

	if (fs_storage_remove(path, 1) < 0) {
		perror("remove\n");
		if (write(nfp, fault, strlen(fault)) < 0)
			printf("write fail!\r\n");
	} else {
		printf("delete %s success\n", path);
		if (write(nfp, success, strlen(success)) < 0)
			printf("write fail!\r\n");
	}
	return 0;
}

static int tcp_pack_file_list(int nfp, char *path, char *type, int form,
			      FILETYPE filetype)
{
	int i = 0;
	int ret;
	char count[32];
	char wifi_info[1024];
	char ackbuf[256];
	struct tm *time;
	char filepath[128];
	struct dirent *ent = NULL;
	DIR *p_dir;
	struct stat fileinfo;
	char *pstr = NULL;
	int type_num, *camera_type;

	printf("read dirent = %s\n", path);

	p_dir = opendir(path);
	if (p_dir == NULL) {
		perror("opendir\n");
		return -1;
	}

	type_num = fs_storage_filetypenum_get();
	camera_type = fs_storage_filetypetbl_get();

	while (NULL != (ent = readdir(p_dir))) {
		if (ent->d_type == 8) {
			memset(count, 0, sizeof(count));
			memset(wifi_info, 0, sizeof(wifi_info));
			memset(ackbuf, 0, sizeof(ackbuf));
			sprintf(count, "%d", i);

			sprintf(filepath, "%s/%s", path, ent->d_name);
			if (stat(filepath, &fileinfo) < 0) {
				printf("stat(%s);\n", filepath);
				perror("stat");
				return -1;
			}

			if (ent->d_name[0] == '.')
				continue;

			strcat(wifi_info, "CMD_GETCAMFILE");
			strcat(wifi_info, "NAME:");
			strcat(wifi_info, ent->d_name);
			strcat(wifi_info, "TYPE:");
			strcat(wifi_info, type);

			strcat(wifi_info, "PATH:");

			pstr = fs_storage_folder_get_bytype(*(camera_type + form), filetype);
			if (pstr == NULL) {
				strcat(wifi_info, "NULL");
			} else {
				strcat(wifi_info, &pstr[sizeof("/mnt/sdcard/") - 1]);
			}
			strcat(wifi_info, "&");

			if (filetype == PICFILE_TYPE) {
				pstr = fs_storage_folder_get_bytype(*(camera_type + form), filetype);
				if (pstr == NULL) {
					strcat(wifi_info, "NULL");
				} else {
					strcat(wifi_info, &pstr[sizeof("/mnt/sdcard/") - 1]);
				}
			} else {
				pstr = fs_storage_folder_get_bytype(*(camera_type + form), THUMBFILE_TYPE);
				if (pstr == NULL) {
					strcat(wifi_info, "NULL");
				} else {
					strcat(wifi_info, &pstr[sizeof("/mnt/sdcard/") - 1]);
				}
			}
			strcat(wifi_info, "&NULL");

			sprintf(&wifi_info[strlen(wifi_info)], "FORM:%dSIZE:%ld",
				form, fileinfo.st_size);
			time = localtime(&fileinfo.st_mtime);
			sprintf(&wifi_info[strlen(wifi_info)],
				"DAY:%04d-%02d-%02d", time->tm_year + 1900,
				time->tm_mon + 1, time->tm_mday);
			sprintf(&wifi_info[strlen(wifi_info)],
				"TIME:%02d:%02d:%02d", time->tm_hour,
				time->tm_min, time->tm_sec);

			strcat(wifi_info, "COUNT:");
			strcat(wifi_info, count);
			strcat(wifi_info, "END");
			printf("wifi_info = %s\n", wifi_info);

			if (0 > write(nfp, wifi_info, strlen(wifi_info)))
				printf("write fail!\r\n");

			if (0 > read(nfp, ackbuf, sizeof(ackbuf)))
				printf("write fail!\r\n");

			if (strcmp(ackbuf, "CMD_NEXTFILE") < 0) {
				printf("CMD_NEXTFILE fault : %s\n", ackbuf);
				break;
			}

			i++;
		}
	}

	if (0 > write(nfp, "CMD_ACK_GETCAMFILE_FINISH",
		      strlen("CMD_ACK_GETCAMFILE_FINISH"))) {
		printf("write fail!\r\n");
	}
	closedir(p_dir);
}

static int tcp_func_set_ssid_pw(int nfp, char *buffer)
{
	char *p = NULL, *p1 = NULL;
	char ssid[33] = {0}, passwd[65] = {0};

	printf("CMD_SETWIFI Get Data:%s\n", buffer);

	p1 = buffer;
	p = strstr(buffer, "WIFINAME:");
	if (p != NULL) {
		p = &p[sizeof("WIFINAME:") - 1];

		while (strstr(p1, "PASSWD:") != NULL) {
			p1 = strstr(p1, "PASSWD:");
			p1 = &p1[sizeof("PASSWD:") - 1];
		}

		if (p1 != buffer) {
			memcpy(ssid, p,
			       (int)p1 - (int)p - sizeof("PASSWD:") + 1);
			if (strlen(p1) > sizeof(passwd)) {
				printf("passwd error:%s\n", p1);
				return -1;
			}
			memcpy(passwd, p1, strlen(p1));
		} else {
			printf("without PASSWD:\n");
			return -1;
		}
	} else {
		printf("without SSID:\n");
		return -1;
	}
	printf("CMD_SETWIFI SSID = %s PASSWD = %s\n",
	       ssid, passwd);

	parameter_getwifiinfo(SSID, PASSWD);
	if (strcmp(ssid, SSID) != 0) {
		printf("%s != %s\n", ssid, SSID);
		return -1;
	}

	parameter_savewifipass(passwd);
	parameter_sav_wifi_mode(0);

	power_reboot();
	return 0;
}

static int tcp_func_appear_ssid(int nfp, char *buffer)
{
	char *p = NULL, *p1 = NULL;
	char ssid[33] = {0}, passwd[65] = {0};

	printf("CMD_APPEARSSID Get Data:%s\n", buffer);

	p1 = buffer;
	p = strstr(buffer, "SSID:");
	if (p != NULL) {
		p = &p[sizeof("SSID:") - 1];

		while (strstr(p1, "PASSWD:") != NULL) {
			p1 = strstr(p1, "PASSWD:");
			p1 = &p1[sizeof("PASSWD:") - 1];
		}

		if (p1 != buffer) {
			memcpy(ssid, p,
			       (int)p1 - (int)p - sizeof("PASSWD:") + 1);
			if (strlen(p1) > sizeof(passwd)) {
				printf("passwd error:%s\n", p1);
				return -1;
			}
			memcpy(passwd, p1, strlen(p1));
		} else {
			printf("without PASSWD:\n");
			return -1;
		}
	} else {
		printf("without SSID:\n");
		return -1;
	}

	printf("CMD_APPEARSSID:\nssid = %s\n passwd = %s\n",
	       ssid, passwd);
	parameter_sav_wifi_mode(1);
	parameter_sav_staewifiinfo(ssid, passwd);

	printf("reboot....\n");
	power_reboot();
	return 0;
}

static int tcp_func_get_file_list(int nfp, char *buffer)
{
	int i, ret= -1;
	char *path;
	int type_num, *camera_type;

	if (strstr(buffer, "CMD_GETFCAMFILETYPE:") == 0) {
		printf("ResolveGetFileList cmd error %s\n", buffer);
		return -1;
	}
	buffer = &buffer[sizeof("CMD_GETFCAMFILETYPE:") - 1];

	printf("type = %s \n", buffer);

	type_num = fs_storage_filetypenum_get();
	camera_type = fs_storage_filetypetbl_get();
	if (strcmp(buffer, "normal") == 0) {
		for (i = 0; i < type_num ; i++) {
			path = fs_storage_folder_get_bytype(*(camera_type + i), VIDEOFILE_TYPE);
			ret = tcp_pack_file_list(nfp, path, "normal", i, VIDEOFILE_TYPE);
			if (ret < 0)
				return ret;
		}
	} else if (strcmp(buffer, "lock") == 0) {
		for (i = 0; i < type_num ; i++) {
			path = fs_storage_folder_get_bytype(*(camera_type + i), LOCKFILE_TYPE);
			ret = tcp_pack_file_list(nfp, path, "lock", i, LOCKFILE_TYPE);
			if (ret < 0)
				return ret;
		}
	} else if (strcmp(buffer, "picture") == 0) {
		for (i = 0; i < type_num ; i++) {
			path = fs_storage_folder_get_bytype(*(camera_type + i), PICFILE_TYPE);
			ret = tcp_pack_file_list(nfp, path, "picture", i, PICFILE_TYPE);
			if (ret < 0)
				return ret;
		}
	}

	return ret;
}

int tcp_func_get_sdcard_status(int nfp, char *buffer)
{
	int ret;
	long long free_size = 0;
	long long total_size = 0;
	char sd_info[128];
	memset(sd_info,0,sizeof(sd_info));
	if (getSD()) {
		ret = fs_sdcard_check_capacity(&free_size,&total_size,NULL);
		if(!ret){
			printf("SDCARD:total size = %lld,free size = %lld\n",total_size,free_size);
		}
		sprintf(sd_info,"CMD_GET_ACK_SDCARD_STATUS_EXIST,TOTALSIZE:%lld,FREESIZE:%lld",total_size,free_size);
		if(sdcard_is_full())
			strcat(sd_info,",CMD_GET_ACK_SDCARD_FULL");
	} else {
		strcpy(sd_info,"CMD_GET_ACK_SDCARD_STATUS_LOSS");
	}
	
	if (0 > write(nfp, sd_info,strlen(sd_info)))
			printf("write fail!\r\n");
	return 0;
}

static int tcp_func_set_on_off_recording(int nfp, char *buffer)
{
	if(getSD() && (!sdcard_is_full()))
	{
		char *p = &buffer[sizeof("CMD_Control_Recording")];

		printf("%s %s\n", buffer, p);
		setting_func_rec_ui(p);
	}
	return 0;
}

static int tcp_func_start_ts_live(int nfp, char *buffer)
{
	char buf[64] = {0};
	struct sockaddr_in sa;
	int len = sizeof(sa);

	if (live_client_num != 0) {
		if (0 > write(nfp, "CMD_ACK_STOP_TS_LIVE",
			      strlen("CMD_ACK_STOP_TS_LIVE"))) {
			printf("write fail!\r\n");
		}
		//video_record_stop_ts_transfer(1);
		return 1;
	}
	live_client_num = 1;

	if (!getpeername(nfp, (struct sockaddr *)&sa, &len)) {
		sprintf(buf, "rtp://%s:%d", inet_ntoa(sa.sin_addr), 20000);
		//printf("video_record_start_ts_transfer(%s);\n", buf);
		video_record_start_ts_transfer(buf);

		if (0 > write(nfp, "CMD_ACK_STOP_TS_LIVE",
			      strlen("CMD_ACK_STOP_TS_LIVE")))
			printf("write fail!\r\n");
	}
    
	return 0;
}

static int tcp_func_stop_ts_live(int nfp, char *buffer)
{
	if (live_client_num == 0)
		return 0;

	live_client_num = 0;
	video_record_stop_ts_transfer(1);
	return 0;
}

static int tcp_func_take_photo(int nfp, char *buffer)
{
	int ret = -1;
    char file_name[128]={0};
    char send_buf[192]={0};
	if(getSD() && (!sdcard_is_full())) {
		ret = video_record_takephoto_stronger(1,file_name);
	}
	if(ret < 0){
		if (0 > write(nfp, "CMD_GET_ACK_TAKE_PHOTO_FAIL",
			      sizeof("CMD_GET_ACK_TAKE_PHOTO_FAIL")))
			printf("write fail!\r\n");
	}else{
	    char* pStr=strstr(file_name,SDCARD_PATH);
        if(pStr)
        {
    	    sprintf(send_buf,"%s,PHOTO_PATH:%s","CMD_GET_ACK_TAKE_PHOTO_SUCCESS",pStr+strlen(SDCARD_PATH));
    		if (0 > write(nfp, send_buf,strlen(send_buf)))
    			printf("write fail!\r\n");
        }

	}
	return 0;
}

static void *tcp_receive(void *arg)
{
	int i;
	int nfp = (int)arg;
	int recbytes;
	char buffer[512] = {0};
	char data[512] = {0};

	pthread_detach(pthread_self());
	printf("tcp_receive : tcp_receive nfp = 0x%x\n", nfp);
	while (g_wifi_is_running) {
		memset(buffer, 0, sizeof(buffer));
		memset(data, 0, sizeof(data));

		printf("tcp_receive : Wait TCP CMD.....\n");

		recbytes = read(nfp, buffer, sizeof(buffer));
		if (0 == recbytes) {
			printf("tcp_receive : disconnect!\r\n");
			goto stop_tcp_receive;
		}

		buffer[recbytes] = '\0';

		cmd_resolve(nfp, buffer);
	}

stop_tcp_receive:

	printf("tcp_receive : stop tcp_receive\n");
    if(get_tracing_is_running())
	{
	    TRACE_APPDATA stTraceData;
	    memset(&stTraceData,0,sizeof(TRACE_APPDATA));
        get_tracing_appdata(&stTraceData);
        if(nfp == stTraceData.reply_fd)
        {   
    		set_tracing_is_running(0);
    		stTraceData.reply_fd = -1;
            stTraceData.bAnswer = -1;
    		set_tracing_appdata(&stTraceData);
        }
    }
    
	if (link_client_num == 0) {
		printf("!!! link client num fault!!!\n");
		return NULL;
	}

	if (--link_client_num == 0)
		tcp_func_stop_ts_live(nfp, NULL);

	shutdown(nfp, 2);
	close(nfp);
	tcp_server_tab[link_client_num] = -1;

	pthread_exit(NULL);
	return NULL;
}

static void *tcp_server_thread(void *arg)
{
	int nfp;
	struct sockaddr_in s_add, c_add;
	int sin_size;
	pthread_t tcpreceive_tid;
	int i;
	int opt = -1;

	pthread_detach(pthread_self());

	for (i = 0; i < MAX_CLIENT_LIMIT_NUM; i++)
		tcp_server_tab[i] = -1;

	tcp_server_fd = socket(AF_INET, SOCK_STREAM, 0);
	if (tcp_server_fd < 0) {
		printf("tcp_server_thread : socket fail ! \r\n");
		pthread_exit(NULL);
	}
	if (setsockopt(tcp_server_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt,
		       sizeof(opt)) < 0) {
		perror("SO_REUSEADDR");
		return NULL;
	}
	printf("socket ok !\r\n");

	bzero(&s_add, sizeof(struct sockaddr_in));
	s_add.sin_family = AF_INET;
	s_add.sin_addr.s_addr = INADDR_ANY;
	s_add.sin_port = htons(TCPPORT);

	if (bind(tcp_server_fd, (struct sockaddr *)(&s_add),
		 sizeof(struct sockaddr)) < 0) {
		perror("bind fail");
		goto stop_tcp_server_thread;
	}
	printf("tcp_server_thread : bind ok !\r\n");

	if (listen(tcp_server_fd, MAX_CLIENT_LIMIT_NUM) < 0) {
		perror("tcp_server_thread : listen fail !\r\n");
		goto stop_tcp_server_thread;
	}
	printf("listen ok\r\n");
	while (g_wifi_is_running) {
		sin_size = sizeof(struct sockaddr_in);

		nfp = accept(tcp_server_fd, (struct sockaddr *)(&c_add),
			     &sin_size);
		if (nfp < 0) {
			perror("tcp_server_thread : accept fail!\r\n");
			goto stop_tcp_server_thread;
		}
		printf("accept ok!\r\nServer get connect from %#x : %#x\r\n",
		       ntohl(c_add.sin_addr.s_addr), ntohs(c_add.sin_port));

		if (link_client_num >= MAX_CLIENT_LIMIT_NUM)
			printf("!!! link [%d] >= listen [%d]!!!\n", link_client_num,
			       MAX_CLIENT_LIMIT_NUM);
		tcp_server_tab[link_client_num++] = nfp;

		printf("tcp_receive : link_client_num = %d\n", link_client_num);

		if (pthread_create(&tcpreceive_tid, NULL, tcp_receive,
				   (void *)nfp) != 0) {
			perror("tcp_server_thread : Create thread error!\n");
			goto stop_tcp_server_thread;
		}

		printf("tcpreceive TID in pthread_create function: %u.\n",
		       tcpreceive_tid);
	}

stop_tcp_server_thread:
	printf("tcp_server_thread : stop tcp_server_thread\n");
	if (tcp_server_fd >= 0) {
		shutdown(tcp_server_fd, 2);
		close(tcp_server_fd);
		tcp_server_fd = -1;
	}
	pthread_exit(NULL);
}

static void *broadcast_thread(void *arg)
{
	socklen_t addr_len = 0;
	char buf[64];
	char name[64];
	size_t len = sizeof(name);
	struct sockaddr_in server_addr;
	char wifi_info[128];
	int opt = -1;
	time_t t;

	pthread_detach(pthread_self());
	broadcast_fd = socket(AF_INET, SOCK_DGRAM, 0);
	if (broadcast_fd < 0) {
		perror("broadcast_thread : socket");
		pthread_exit(NULL);
	}
	printf("broadcast_thread socketfd = %d\n", broadcast_fd);

	memset(&server_addr, 0, sizeof(server_addr));
	server_addr.sin_family = AF_INET;
	server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	server_addr.sin_port = htons(UDPPORT);
	addr_len = sizeof(server_addr);

	if (setsockopt(broadcast_fd, SOL_SOCKET, SO_BROADCAST, (char *)&opt,
		       sizeof(opt)) < 0) {
		perror("broadcast_thread setsockopt SO_BROADCAST");
		goto stop_broadcast_thread;
	}
	if (setsockopt(broadcast_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt,
		       sizeof(opt)) < 0) {
		perror("broadcast_thread setsockopt SO_REUSEADDR");
		goto stop_broadcast_thread;
	}

	if (bind(broadcast_fd, (struct sockaddr *)&server_addr, addr_len) < 0) {
		perror("broadcast_thread bind");
		goto stop_broadcast_thread;
	}

	gethostname(name, len);
	while (g_wifi_is_running) {
		printf("Wait Discover....\n");
		addr_len = sizeof(server_addr);
		memset(&server_addr, 0, sizeof(server_addr));
		memset(buf, 0, sizeof(buf));
		if (recvfrom(broadcast_fd, buf, 64, 0,
			     (struct sockaddr *)&server_addr, &addr_len) < 0) {
			perror("broadcast_thread recvfrom");
			goto stop_broadcast_thread;
		}
		printf("broadcast_thread : from: %s port: %d > %s\n",
		       inet_ntoa(server_addr.sin_addr),
		       ntohs(server_addr.sin_port), buf);

		if (strcmp("CMD_DISCOVER", buf) == 0) {
			memset(wifi_info, 0, sizeof(wifi_info));

			strcat(wifi_info, "CMD_DISCOVER_CVR:WIFINAME:");
			strcat(wifi_info, SSID);

			strcat(wifi_info, "SID:");
			linux_get_mac(&wifi_info[strlen(wifi_info)]);
			strcat(wifi_info, "END");

			addr_len = sizeof(server_addr);
			printf("sendto: %s port: %d > %s\n",
			       inet_ntoa(server_addr.sin_addr),
			       ntohs(server_addr.sin_port), wifi_info);
			if (sendto(broadcast_fd, wifi_info, strlen(wifi_info),
				   0, (struct sockaddr *)&server_addr,
				   addr_len) < 0) {
				perror("broadcast_thread recvfrom");
				goto stop_broadcast_thread;
			}
		}
	}

stop_broadcast_thread:
	printf("stop broadcast_thread\n");
	if (broadcast_fd >= 0) {
		shutdown(broadcast_fd, 2);
		close(broadcast_fd);
		broadcast_fd = -1;
	}
	pthread_exit(NULL);
}

void wifi_management_start(void)
{
	if (g_wifi_is_running) {
		printf("Wifi is now runnning, don't start again!\n");
		return;
	}

	g_wifi_is_running = 1;

	printf("This is wifi_management_start\n");

	WlanServiceSetPower("on");

	if (parameter_get_wifi_mode()) {
		printf("start station\n");
		parameter_getwifistainfo(SSID, PASSWD);
		WlanServiceSetMode("station", SSID, PASSWD);
	} else {
		printf("start access point\n");
		parameter_getwifiinfo(SSID, PASSWD);
		WlanServiceSetMode("ap", SSID, PASSWD);
	}

	if (pthread_create(&broadcast_tid, NULL, broadcast_thread, NULL) != 0)
		printf("Create thread error!\n");

	if (pthread_create(&tcp_server_tid, NULL, tcp_server_thread, NULL) != 0)
		printf("Createthread error!\n");

	runapp("/usr/local/sbin/lighttpd -f /usr/local/etc/lighttpd.conf");
}

void wifi_management_stop(void)
{
	int i;

	if (!g_wifi_is_running) {
		printf("Wifi is not runnning, cannot stop it!\n");
		return;
	}

	g_wifi_is_running = 0;

	printf("stop lighttpd...!\n");
	runapp("kill -15 $(pidof lighttpd)");

	WlanServiceSetPower("off");
}

int tcp_func_set_on_off_tracing(int nfp, char *buffer)
{
	//CMD_TRACING_ON:X=xx,Y=xx,W=xx,H=xx  CMD_TRACING_OFF
	//CMD_ACK_TRACING_DATA:X=xx,Y=xx,W=xx,H=xx
	char buf[32];
	int len;
	TRACE_APPDATA stTraceData;
	memset(&stTraceData,0,sizeof(TRACE_APPDATA));
    get_tracing_appdata(&stTraceData);
	if(strstr(buffer,"CMD_TRACING_ON") && (!get_tracing_is_running()))
	{
		char* pSt1=strstr(buffer,"X=");
		char* pSt2=strstr(buffer,"Y=");
		char* pSt3=strstr(buffer,"W=");
		char* pSt4=strstr(buffer,"H=");
		if(pSt1 && pSt2)
		{
			len = pSt2-1-pSt1-2;
			memcpy(buf,pSt1+2,len);
			buf[len]='\0';
			stTraceData.tractoNet.trac_x=atoi(buf);
		}
		if(pSt2 && pSt3)
		{
			len = pSt3-1-pSt2-2;
			memcpy(buf,pSt2+2,len);
			buf[len]='\0';
			stTraceData.tractoNet.trac_y=atoi(buf);
		}
		if(pSt3 && pSt4)
		{
			len = pSt4-1-pSt3-2;
			memcpy(buf,pSt3+2,len);
			buf[len]='\0';
			stTraceData.tractoNet.trac_w=atoi(buf);
		}
		if(pSt4)
		{
			strcpy(buf,pSt4+2);
			stTraceData.tractoNet.trac_h=atoi(buf);
		}
		if(pSt1 && pSt2 && pSt3 && pSt4)
		{
			DEBUG_INFO("trace set start:%d--%d--%d--%d",stTraceData.tractoNet.trac_x,stTraceData.tractoNet.trac_y,
				stTraceData.tractoNet.trac_w,stTraceData.tractoNet.trac_h);
            stTraceData.bAnswer = -1;
            stTraceData.reply_fd = nfp;
			set_tracing_appdata(&stTraceData);
			set_tracing_is_running(1);
		}
	}
    else if(strstr(buffer,"CMD_TRACING_OFF") && get_tracing_is_running())
	{
	    //if or not same connect
	    if(nfp == stTraceData.reply_fd)
        {   
    		set_tracing_is_running(0);
    		stTraceData.reply_fd = -1;
            stTraceData.bAnswer = -1;
    		set_tracing_appdata(&stTraceData);
        }
	}
    else if(strstr(buffer,"CMD_TRACING_ANSWER") && get_tracing_is_running())
	{
	    char* pSt = strstr(buffer,"CMD_TRACING_ANSWER:");
        if(pSt)
        {
            strcpy(buf,pSt+strlen("CMD_TRACING_ANSWER:"));
			stTraceData.bAnswer=atoi(buf);
            set_tracing_appdata(&stTraceData);
            DEBUG_INFO("CMD_TRACING_ANSWER:%d",stTraceData.bAnswer);
        }
    }

	return 0;
}

int tcp_func_motor_control(int nfp, char *buffer)
{
    //CMD_Control_Motor|direc=1/2,state=1/2/3
    //direc:1--top;2--bottom
    //state:1--short press;2--long press;3--long release
    char buf[16];
    char* pStar = strstr(buffer,"direc=");
    char* pStar1 = strstr(buffer,"state=");
    int direc=0,state=0;
    if(pStar && pStar1)
    {
       memset(buf,0,sizeof(buf));
       strcpy(buf,pStar+strlen("direc=")); 
       direc = atoi(buf);
       memset(buf,0,sizeof(buf));
       strcpy(buf,pStar1+strlen("state=")); 
       state = atoi(buf);
    }
    //DEBUG_INFO("motor direc = %d,state = %d",direc,state);
    motor_pwm_crtl(direc,state);
    return 0;
}

const struct type_cmd_func cmd_tab[] = {
	{tcp_func_get_ssid_pw,			        "CMD_GETWIFI",},
	{tcp_func_set_ssid_pw,			        "CMD_SETWIFI",},
	{tcp_func_get_file_list,		        "CMD_GETFCAMFILE",},
	{tcp_func_delete_file,			        "CMD_DELFCAMFILE",},
	{tcp_func_appear_ssid,			        "CMD_APPEARSSID",},
	{setting_cmd_resolve,			        "CMD_ARGSETTING",},
	{setting_get_cmd_resolve,		        "CMD_GET_ARGSETTING",},
	{tcp_func_get_format_status,		    "CMD_GET_FORMAT_STATUS",},
	{tcp_func_get_sdcard_status,		    "CMD_GET_SDCARD_STATUS",},
	{tcp_func_set_on_off_recording,		    "CMD_Control_Recording",},
	{tcp_func_get_on_off_recording,		    "CMD_GET_Control_Recording",},
	{tcp_func_start_ts_live,		        "CMD_RTP_TS_TRANS_START",},
	{tcp_func_stop_ts_live,			        "CMD_RTP_TS_TRANS_STOP",},
	{debug_setting_cmd_resolve,		        "CMD_DEBUG_ARGSETTING",},
	{debug_setting_get_cmd_resolve,		    "CMD_GET_DEBUG_ARGSETTING",},
	{tcp_func_take_photo,			        "CMD_Control_Photograph",},
	{tcp_func_ota_updata,			        "CMD_OTA_Update",},
	{tcp_func_upload_file,			        "CMD_OTA_Upload_File",},
	{tcp_func_set_on_off_tracing,		    "CMD_Control_Tracing",},
    {tcp_func_motor_control,		        "CMD_Control_Motor",}
};

static int cmd_resolve(int fd, char *cmdstr)
{
	int i = 0;

	DEBUG_INFO("cmd_resolve = %s\n", cmdstr);
	for (i = 0; i < sizeof(cmd_tab) / sizeof(cmd_tab[1]); i++) {
		if (strstr(cmdstr, cmd_tab[i].cmd) != 0) {
			if (cmd_tab[i].func != NULL)
				cmd_tab[i].func(fd, cmdstr);
			return 0;
		}
	}

	return -1;
}
